package xaj.main;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.LinkedList;

import java_cup.internal_error;
import ppg.PPG;
import util.StreamReader;
import xaj.scc.visit.Visitor_Giorgio_01;
import xaj.selector.Selector;
import xaj.selector.SelectorImpl;

public class XAJC {
	
	private static final String HEADER = "xajc: ";
	
	//Pasta de destino do código compilado (código que está na pasta SOURCE) 
	private final static String OUTPUT = "output";
	//Diretório temporário no qual será gerado o arquivo xaj.ppg, etc...
	//private final static String TMP = ".";
	private final static String TMP = "tmp";
	//Nome do arquivo ppg gerado
	private final static String PPG_NAME = "xaj.ppg";
	//Nome do arquivo cup gerado
	private final static String CUP_NAME = "xaj_ppg.cup";
	//Nome do parser
	private final static String PARSER_NAME = "Grm";
	//Nome do pacote do parser
	private final static String PARSER_PACKAGE = "xaj.xajc.parse";
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String path = ".", output = ".";
		try {
			for (int i = 0; i < args.length; ++i) {
				if (args[i].equalsIgnoreCase("-sourceroots")) {
					if (i + 1 < args.length)
						path = args[++i];
					else
						throw new Exception(
								"No source root specified after -sourceroots");
				} else if (args[i].equals("-d")) {
					if (i + 1 < args.length)
						output = args[++i];
					else
						throw new Exception("No output specified after -d");
				} else {
					throw new Exception("Invalid switch: " + args[i]);
				}
			}
		} catch (Exception e) {
			System.err.println(HEADER + e.getMessage());
			usage();
		}
		
		/**
		 * Compila as classes sintáticas
		 */
		compileSyntaxClass(path);
				
		/**
		 * Compila o arquivo ppg e gera a gramática Grm
		 */
		//compilePPG();

		//------------------------------------------------------------
		
		/**
		 * Compila a parser gerado a partir do arquivo ppg
		 */
		//compileParser();
		
		//Os argumentos foram colocados aqui, depois mudamos isso
		//Todos esses parâmetros são passados para o compilador do abc
		//Para obter mais informações sobre eles, cheque os possíveis parâmetros do abc
		/*args = new String[6];
		//Parâmetros -d
		args[0] = "-d";
		args[1] = Selector.ROOT + "/" + OUTPUT;
		
		//Parâmetros -sourceroots
		args[2] = "-sourceroots";
		args[3] = Selector.SOURCE;
		
		//Parâmetros -ext
		args[4] = "-ext";
		args[5] = "xaj.xajc";*/
		
		//args[4] = "tests/Teste1.java";
			
		
		//############################################
		//abc.main.Main.main(args);
		//abc.main.Main.resetStatic();

		System.out.println("Funcionou, que maravilha!!!");
	}

	//----------------------------------------------------------------------------
	
	protected static void compileParser() {
		try {
			//Executa o comando javac para compilar a classe sym gerada
			executeCommand("javac sym.java");
			
			//Executa comando javac para compilar o parser Grm.java
			executeCommand("javac " + PARSER_NAME + ".java");
			
		} catch (IOException e) {
			System.err.println("Erro ao executar comando javac");
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	protected static void executeCommand(String command) throws IOException, InterruptedException {
		//Executa o comando
		Process proc = Runtime.getRuntime().exec(command);
		
		// any error message?
        StreamReader errorGobbler = new StreamReader(proc.getErrorStream(), "ERROR");            
        
        // any output?
        StreamReader outputGobbler = new StreamReader(proc.getInputStream(), "OUTPUT");
            
        // kick them off
        errorGobbler.start();
        outputGobbler.start();
        
       // any error???
        int exitVal = proc.waitFor();
        System.out.println("ExitValue: " + exitVal); 

	}
	// ----------------------------------------------------------------------------
	
	protected static void usage() {
		/**
		 * @TODO - imprirmir uma mensagem mais adequada
		 */
		System.err.println("Usage: " + HEADER + " [-sourceroots root] [-d output]");
		System.exit(1);
	}
	
	/**
	 * Compile all syntax class from path
	 * @args path Path of the sources
	 */
	public static void compileSyntaxClass(String path) {
		/**
		 * Separa as classes sinticas que devem ser compiladas
		 */
		Collection<String> sources = Loadder.loadSourceRoots(path);
		Selector selector = new SelectorImpl();
		sources = selector.selectSyntaxClass(sources);
		
		//for(String s : sources)
		//	System.out.println(s);
		
		String args[] = new String[sources.size() + 4];
		int i = 0;
		args[i++] = "-d";
		args[i++] = "output";
		args[i++] = "-ext";
		args[i++] = "xaj.scc";
		for(String s : sources) {
			args[i++] = s; 
		}
		
		//Coisa que o Giorgio colocou
		//---------------------------
		Visitor_Giorgio_01.init();
		//----------------------------
		abc.main.Main.main(args);
		//Coisa do Giorgio
		//------------------------
		Visitor_Giorgio_01.end();
		//-----------------------
		abc.main.Main.resetStatic();
		
		//System.out.println("Tamanho da lista de argumentos: " + i);
		
		System.out.println("Executou o Syntax Class Compiler");

	}
	
	/**
	 * Compile file xaj.ppg which was generated when the syntax
	 * classes were compiled
	 */
	protected static void compilePPG() {	
		//Nome do arquivo de entrada - padrão será sempre xaj.ppg localizado na pasta tmp
		String args[] = new String[3];
		args[0] = Selector.ROOT + "/" + TMP + "/" + PPG_NAME;
		
		//Nome do arquivo de saída
		args[1] = "-o";
		args[2] = Selector.ROOT + "/" + TMP + "/" + CUP_NAME;
		
		PPG.main(args);
		
		//Gera a gramática Grm
		String args1[] = new String[5];
		
		//Nome do parser
		args1[0] = "-parser";
		args1[1] = PARSER_NAME;
		
		//Nome do pacote do parser
		args1[2] = "-package";
		args1[3] = PARSER_PACKAGE;		
		
		//Nome do arquivo de entrada
		args1[4] = Selector.ROOT + "/" + TMP + "/" + CUP_NAME;
		
		try {
			java_cup.Main.main(args1);
			
		} catch (internal_error e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//System.out.println("Compilou o arquivo xaj.ppg");
	}
}
